﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="WorkflowInstance.cs" company="Microsoft">
//   Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------

namespace TrackingStateMachine
{
    using System;
    using System.Activities;
    using System.ComponentModel;
    using System.Diagnostics;

    using Microsoft.Activities.Extensions.Tracking;

    using TrackingStateMachine.Activities;

    /// <summary>
    ///   The WorkflowInstance
    /// </summary>
    public class WorkflowInstance : INotifyPropertyChanged
    {
        #region Static Fields

        /// <summary>
        ///   The workflow 1 definition.
        /// </summary>
        internal static readonly AuditWF Workflow1Definition = new AuditWF();

        #endregion

        #region Fields

        /// <summary>
        ///   The view.
        /// </summary>
        private readonly IWorkflowView view;

        /// <summary>
        ///   The is loaded.
        /// </summary>
        private bool isLoaded;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="WorkflowInstance"/> class.
        /// </summary>
        /// <param name="view">
        /// The view. 
        /// </param>
        /// <param name="stateMachineStateTracker">
        /// The StateTracker (optional) 
        /// </param>
        public WorkflowInstance(IWorkflowView view, StateMachineStateTracker stateMachineStateTracker = null)
        {
            this.view = view;
            this.StateTracker = stateMachineStateTracker ?? new StateMachineStateTracker(Workflow1Definition);
        }

        #endregion

        #region Public Events

        /// <summary>
        ///   The property changed.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region Public Properties

        /// <summary>
        ///   Gets or sets Host.
        /// </summary>
        public WorkflowApplication Host { get; set; }

        /// <summary>
        ///   Gets Id.
        /// </summary>
        public Guid Id
        {
            get
            {
                return this.Host == null ? this.StateTracker.InstanceId : this.Host.Id;
            }
        }

        /// <summary>
        ///   Gets or sets a value indicating whether IsLoaded.
        /// </summary>
        public bool IsLoaded
        {
            get
            {
                return this.isLoaded;
            }

            set
            {
                this.isLoaded = value;
                this.NotifyChanged("IsLoaded");
            }
        }

        /// <summary>
        ///   Gets the StateTracker.
        /// </summary>
        public StateMachineStateTracker StateTracker { get; private set; }

        #endregion

        #region Public Methods and Operators

        /// <summary>
        ///   The load.
        /// </summary>
        public void Load()
        {
            this.CreateWorkflowApplication();
            this.Host.Load(this.StateTracker.InstanceId);
            this.IsLoaded = true;
        }

        /// <summary>
        ///   The new.
        /// </summary>
        public void New()
        {
            this.CreateWorkflowApplication();
            this.IsLoaded = true;
        }

        /// <summary>
        ///   The run.
        /// </summary>
        public void Run()
        {
            this.Host.Run();
        }

        /// <summary>
        ///   The unload.
        /// </summary>
        public void Unload()
        {
            try
            {
                if (this.IsLoaded)
                {
                    this.Host.Unload();
                    this.IsLoaded = false;
                }
            }
            catch (Exception exception)
            {
                Trace.WriteLine(exception.Message);
            }
        }

        #endregion

        #region Methods

        /// <summary>
        ///   The create workflow application.
        /// </summary>
        private void CreateWorkflowApplication()
        {
            this.Host = new WorkflowApplication(Workflow1Definition)
                {
                    Idle = this.view.OnIdle, 
                    Aborted = this.view.OnAbort, 
                    Completed = this.view.OnComplete, 
                    InstanceStore = this.view.InstanceStore, 
                    OnUnhandledException = this.view.OnUnhandledException, 
                    PersistableIdle = this.view.PersistableIdle, 
                    Unloaded = this.view.OnUnload
                };

            // Setup tracking in UI
            this.Host.Extensions.Add(new MainWindow.TextTracker());
            this.Host.Extensions.Add(this.StateTracker);
            //this.Host.Extensions.Add(new CustomerPersistenceParticipant());
            this.Host.Extensions.Add(new HistoryTrackingParticipant());

            // Setup the persistence participant
            this.Host.Extensions.Add(new StateTrackerPersistenceProvider(this.StateTracker));
        }

        /// <summary>
        /// The on property changed.
        /// </summary>
        /// <param name="propertyName">
        /// The property name. 
        /// </param>
        private void NotifyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion
    }
}